home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 37
/
Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso
/
Aminet
/
dev
/
cross
/
devpic.lha
/
devpic
/
source
/
picasm
/
config.c
next >
Wrap
C/C++ Source or Header
|
2000-02-27
|
7KB
|
299 lines
/*
* picasm -- config.c
*
* handles configuration fuse setting with the CONFIG-directive
*
* Timo Rossi <trossi@iki.fi>
*
*/
#include <stdio.h>
#include <string.h>
#include "picasm.h"
/*
* Check Yes/No (or Disable(d)/Enable(d) or On/Off) strings for CONFIG
*
* returns: 0=no, 1=yes, -1=error
*
*/
static int
config_yes_no(char *s)
{
if(strcasecmp(s, "yes") == 0 || strcasecmp(s, "on") == 0 ||
strncasecmp(s, "enable", 6) == 0)
return 1;
else if(strcasecmp(s, "no") == 0 || strcasecmp(s, "off") == 0 ||
strncasecmp(s, "disable", 7) == 0)
return 0;
else
return -1; /* error */
}
/*
* selstr consists of NUL-terminated strings with two NULs in the end
* If str matches one of the components of selstr, the index of
* that component (starting from zero) is returned,
* if no match is found, -1 is returned.
*/
static int
strsel(char *selstr, char *str)
{
int sel = 0;
while(*selstr != '\0') {
if(strcasecmp(selstr, str) == 0)
return sel;
selstr += strlen(selstr)+1;
sel++;
}
return -1;
}
/*
* parse the CONFIG directive
*
* (the separate code protections of PIC14000 are not currently,
* and neither are the partial protections on some PICs)
*
*/
void
parse_config(void)
{
static char symname[256];
int t;
for(;;) {
if(token_type != TOK_IDENTIFIER) {
cfg_error:
error(1, "CONFIG syntax error");
return;
}
strcpy(symname, token_string);
get_token();
/* hmm... this is a little kludge, but as
the tokenizer now makes 'local id's from
the valid config strings, this must be used... */
if(token_type != TOK_LOCAL_ID) {
if(token_type != TOK_EQUAL) {
error(1, "'=' expected");
return;
}
get_token();
if(token_type != TOK_IDENTIFIER)
goto cfg_error;
}
switch(strsel("OSC\0WDT\0CP\0PWRT\0MCLR\0BOD\0MPE\0", symname)) {
case 0: /* OSC */
if((t = strsel("LP\0XT\0HS\0RC\0INTRC\0INTRC_CLKOUT\0"
"EXTRC\0EXTRC_CLKOUT\0IN\0", token_string)) < 0)
goto cfg_error;
switch(pic_type->fusetype) {
case FUSE_12C5XX:
if(t >= 2 && t != 4 && t != 6) {
error(1, "Invalid oscillator type %s for PIC%s",
token_string, pic_type->name);
return;
}
if(t >= 2)
t >>= 2;
config_fuses = (config_fuses & 0xffc) | t;
break;
case FUSE_12C6XX:
if(t == 3 || t >= 8) {
error(1, "Invalid oscillator type %s for PIC%s",
token_string, pic_type->name);
return;
}
config_fuses = (config_fuses & 0x3ff8) | t;
break;
case FUSE_14000:
if(t != 2 && t != 4 && t != 8) { /* accept both IN and INTRC */
error(1, "Invalid oscillator type %s for PIC%s",
token_string, pic_type->name);
return;
}
config_fuses = (config_fuses & 0x3ffe) | (t != 2);
break;
case FUSE_16C5X:
case FUSE_16F8X:
case FUSE_16CXX1:
case FUSE_16CXX2:
case FUSE_16C55X:
case FUSE_16C62X:
case FUSE_16C6XA:
case FUSE_16C71X:
case FUSE_16C715:
if(t >= 4) {
error(1, "Invalid oscillator type %s for PIC%s",
token_string, pic_type->name);
return;
}
config_fuses = (config_fuses & 0x3ffc) | t;
break;
}
break;
case 1: /* WDT - watchdog timer */
if((t = config_yes_no(token_string)) < 0)
goto cfg_error;
switch(pic_type->fusetype) {
case FUSE_12C6XX:
config_fuses = (config_fuses & 0x3ff7) | (t ? 8 : 0);
break;
default:
config_fuses = (config_fuses & 0x3ffb) | (t ? 4 : 0);
break;
}
break;
case 2: /* CP - code protect */
/* partial protection is not supported */
if((t = config_yes_no(token_string)) < 0)
goto cfg_error;
switch(pic_type->fusetype) {
case FUSE_16C5X:
case FUSE_12C5XX:
config_fuses = (config_fuses & 0xff7) | (t ? 0 : 8);
break;
case FUSE_12C6XX:
config_fuses = (config_fuses & 0x009f) | (t ? 0 : 0x3f60);
break;
case FUSE_16CXX1: /* 1 code protect bit */
config_fuses = (config_fuses & 0x3fef) | (t ? 0 : 0x10);
break;
case FUSE_16CXX2: /* 2 code protect bits */
config_fuses = (config_fuses & 0x3fcf) | (t ? 0 : 0x30);
break;
case FUSE_16F8X:
config_fuses = (config_fuses & 0x000f) | (t ? 0 : 0x3ff0);
break;
case FUSE_16C71X:
config_fuses = (config_fuses & 0x004f) | (t ? 0 : 0x3fb0);
break;
case FUSE_16C6XA:
case FUSE_16C62X: /* 2 code protect bits, replicated */
case FUSE_16C55X:
case FUSE_16C715:
config_fuses = (config_fuses & 0x00cf) | (t ? 0 : 0x3f30);
break;
case FUSE_14000:
config_fuses = (config_fuses & 0x3f4f) | (t ? 0 : 0x00b0);
break;
}
break;
case 3: /* PWRT - power-up timer */
if((t = config_yes_no(token_string)) < 0)
goto cfg_error;
switch(pic_type->fusetype) {
case FUSE_16CXX1:
case FUSE_16CXX2:
config_fuses = (config_fuses & 0x3ff7) | (t ? 8 : 0);
break;
case FUSE_16C6XA:
case FUSE_16C55X:
case FUSE_16F8X:
case FUSE_16C71X:
case FUSE_16C715:
case FUSE_16C62X:
case FUSE_14000:
config_fuses = (config_fuses & 0x3ff7) | (t ? 0 : 8);
break;
case FUSE_12C6XX:
config_fuses = (config_fuses & 0x3fef) | (t ? 0 : 0x10);
break;
case FUSE_16C5X:
case FUSE_12C5XX:
error(1, "No power-up timer in PIC%s", pic_type->name);
return;
}
break;
case 4: /* MCLR - enable/disable MCLR (8-pin PICs) */
if((t = config_yes_no(token_string)) < 0)
goto cfg_error;
switch(pic_type->fusetype) {
case FUSE_12C5XX:
config_fuses = (config_fuses & 0xfef) | (t ? 0x10 : 0);
break;
case FUSE_12C6XX:
config_fuses = (config_fuses & 0x3f7f) | (t ? 0x80 : 0);
break;
default:
error(1,"No MCLRE in PIC%s", pic_type->name);
return;
}
break;
case 5: /* BOD - brown-out detect */
if((t = config_yes_no(token_string)) < 0)
goto cfg_error;
switch(pic_type->fusetype) {
case FUSE_16C62X:
case FUSE_16C6XA:
case FUSE_16C71X:
case FUSE_16C715:
config_fuses = (config_fuses & 0x3fbf) | (t ? 0x40 : 0);
break;
default:
error(1,"No BODEN in PIC%s", pic_type->name);
return;
}
break;
case 6: /* MPE - memory parity error */
if((t = config_yes_no(token_string)) < 0)
goto cfg_error;
switch(pic_type->fusetype) {
case FUSE_16C715:
config_fuses = (config_fuses & 0x3f7f) | (t ? 0x80 : 0);
break;
default:
error(1,"No MPEEN in PIC%s", pic_type->name);
return;
}
break;
default:
goto cfg_error;
}
get_token();
if(token_type != TOK_COMMA)
break;
get_token();
}
}